//
// Created by Administrator on 2023/6/27.
//

#include "WidgetFactory.h"

#include <unordered_map>
#include <mutex>
#include <cassert>
#include <iostream>

class WidgetFactory::Impl : public std::enable_shared_from_this<Impl> {
    std::mutex mtx_;
    std::unordered_map<int, std::weak_ptr<Widget>> cache_;

    void deleteCache(Widget *p) {
        if (p) {
            std::lock_guard lk(mtx_);
            auto iter = cache_.find(p->getId());
            assert(iter != cache_.end());
            if (iter->second.expired()) {
//            if (!iter->second.lock()) {
                cache_.erase(p->getId());
            }
        }
    }
public:
    std::shared_ptr<Widget> getWidget(int id) {
        std::shared_ptr<Widget> pWidget;
        std::lock_guard lk(mtx_);

        auto &&wpWidget = cache_[id];
        pWidget = wpWidget.lock();
        if (!pWidget) {
            pWidget.reset(new Widget(id), [wpImpl = std::weak_ptr<Impl>(shared_from_this())](Widget *p) {
                auto pImpl = wpImpl.lock();
                if (pImpl) {
                    pImpl->deleteCache(p);
                }
                delete p;
            });
            wpWidget = pWidget;
        }
        return pWidget;
    }
};

WidgetFactory::WidgetFactory()
    : pImpl_(std::make_shared<Impl>()) {

}

WidgetFactory::~WidgetFactory() = default;

std::shared_ptr<Widget> WidgetFactory::getWidget(int id) {
    return pImpl_->getWidget(id);
}

